module permutation(
    input [7:0]const,
    input [319:0]Sin,
    output [319:0]Sout
    );
wire [63:0]pc[4:0];
wire [63:0]ps[4:0];
wire [63:0]x[4:0];
wire [63:0]y[4:0];

//轮常数加
assign pc[0]=Sin[63:0];
assign pc[1]=Sin[127:64];
assign pc[2]=Sin[191:128]^{56'b0,const};
assign pc[3]=Sin[255:192];
assign pc[4]=Sin[319:256];

//S盒
genvar i;
generate
    for(i=0;i<64;i=i+1)
    begin
        //X5前异或
        assign x[0][i]=pc[0][i]^pc[4][i];
        assign x[1][i]=pc[1][i];
        assign x[2][i]=pc[1][i]^pc[2][i];
        assign x[3][i]=pc[3][i];
        assign x[4][i]=pc[3][i]^pc[4][i];

        //X5
        assign y[0][i]=x[0][i]^((~x[1][i])&x[2][i]);
        assign y[1][i]=x[1][i]^((~x[2][i])&x[3][i]);
        assign y[2][i]=x[2][i]^((~x[3][i])&x[4][i]);
        assign y[3][i]=x[3][i]^((~x[4][i])&x[0][i]);
        assign y[4][i]=x[4][i]^((~x[0][i])&x[1][i]);

        //X5后异或
        assign ps[0][i]=y[0][i]^y[4][i];
        assign ps[1][i]=y[0][i]^y[1][i];
        assign ps[2][i]=~y[2][i];
        assign ps[3][i]=y[2][i]^y[3][i];
        assign ps[4][i]=y[4][i];
    end
endgenerate

//扩散层
assign Sout[63:0]   =ps[0]^{ps[0][18:0],ps[0][63:19]}^{ps[0][27:0],ps[0][63:28]};
assign Sout[127:64] =ps[1]^{ps[1][60:0],ps[1][63:61]}^{ps[1][38:0],ps[1][63:39]};
assign Sout[191:128]=ps[2]^{ps[2][0],ps[2][63:1]}^{ps[2][5:0],ps[2][63:6]};
assign Sout[255:192]=ps[3]^{ps[3][9:0],ps[3][63:10]}^{ps[3][16:0],ps[3][63:17]};
assign Sout[319:256]=ps[4]^{ps[4][6:0],ps[4][63:7]}^{ps[4][40:0],ps[4][63:41]};

endmodule
